#include "../src/nominal.hh"

#include <cassert>
#include <iostream>

namespace
{
using namespace playerpiano;

struct LogPRatingTestDatum 
{ 
  struct
    {
      unsigned int      rating;
      float             alpha[4];
      float             logbeta;
    }                                   inputs;
  struct
    {
      float             logp;
      float             dlogbeta;
      float             ddlogbeta;
    }                                   outputs;
};

void
test_logprating (void)
{
  LogPRatingTestDatum data[] = 
    {{{3, {0.947375, 0.298482, 0.689616, 0.114157},  0.497138}, {-2.1248, -1.2957, -2.16913}}, {{3, {0.157952, 0.30186,  0.131109, 0.119375},  0.623508}, {-2.37582, -1.54164, -2.44303}}, {{3, {0.698482,  0.935676, 0.412585, 0.894346},  0.00205476}, {-2.32768, -1.30794, -1.97954}}, {{3, {0.00397272,  0.385424, 0.917928, 0.54418},  0.120771}, {-2.14747, -1.15479, -1.86415}}, {{2, {0.0836416,  0.271459, 0.0878399, 0.283715},  0.136266}, {-1.8063, -0.654887, -1.12657}}, {{1, {0.972976,  0.398223, 0.169558, 0.639128},  0.815024}, {-3.28846, -2.7956, -3.76952}}, {{3, {0.0963632,  0.0384496, 0.519753, 0.191516},  0.397881}, {-2.17047, -1.19137, -1.91213}}, {{0, {0.102774,  0.107168, 0.29717, 0.395826}, 0.0988009}, {-0.558285, 0.590566,  0.116358}}, {{1, {0.721744, 0.379243, 0.851646, 0.97803},  0.638103}, {-2.73047, -2.26855, -3.21746}}, {{0, {0.107784,  0.763806, 0.694315, 0.501836}, 0.134807}, {-0.375739,  0.587409, -0.174458}}};

  for (unsigned int i = 0; i < sizeof (data) / sizeof (data[0]); ++i)
    {
      Nominal nominal (data[i].inputs.alpha, 0, 0, 1, 4);
      Rating rating = { 0, data[i].inputs.rating };
      float dlogbeta = drand48 ();
      float ddlogbeta = drand48 ();

      float logp = nominal.logprating (rating, 
                                       0,
                                       exp (data[i].inputs.logbeta),
                                       dlogbeta,
                                       ddlogbeta);

      assert (fabs (logp - data[i].outputs.logp) <=
              1e-4 * (1 + fabs (logp) + fabs (data[i].outputs.logp)) ||
              (std::cerr << logp << " ?= " << data[i].outputs.logp << std::endl,
               0));

      assert (fabs (dlogbeta - data[i].outputs.dlogbeta) <=
              1e-4 * (1 + fabs (dlogbeta) + fabs (data[i].outputs.dlogbeta)) ||
              (std::cerr << dlogbeta << " ?= " << data[i].outputs.dlogbeta << std::endl,
               0));

      assert (fabs (ddlogbeta - data[i].outputs.ddlogbeta) <=
              1e-4 * (1 + fabs (ddlogbeta) + fabs (data[i].outputs.ddlogbeta)) ||
              (std::cerr << ddlogbeta << " ?= " << data[i].outputs.ddlogbeta << std::endl,
               0));
    }
}

}

int 
main (void) 
{
  srand48 (69);

  test_logprating ();

  return 0;
}
